package piwan;
import java.awt.event.KeyEvent;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedList;

import piwan.gui.GameGui;
import piwan.gui.LabelListOverlay;

public class InfoOverlay extends LabelListOverlay implements RegionSelector.Listener {
	static private final Colour HIGHLIGHT_COLOUR = new Colour(0.6,0.6,0.8,0.9);
	private GameState gs;
	private boolean ctrl=false,shift=false;
	private BorderRenderer.Border border;
	private Region hover = null;
	private ArrayList<Polygon> polys = new ArrayList<Polygon>();
	private boolean visible=true;
	
	private class Handler extends EventHandler {
		public boolean onKeyPressed(KeyEvent e) {
			if(e.getKeyCode() == KeyEvent.VK_CONTROL  && !ctrl) { ctrl = true; performUpdate(); }
			else if(e.getKeyCode() == KeyEvent.VK_SHIFT && !shift) { shift = true; performUpdate(); }
			return false;
		}
		
		public boolean onKeyReleased(KeyEvent e) {
			if(e.getKeyCode() == KeyEvent.VK_CONTROL) { ctrl = false; performUpdate(); }
			else if(e.getKeyCode() == KeyEvent.VK_SHIFT) { shift = false; performUpdate(); }
			return false;
		}
	}
	
	public InfoOverlay(UserGame ug) {
		super(ug, 20, new Vector2(1.0-778.0/ug.getWidth(),-1.0 + 96.0/ug.getHeight()), 745.0/ug.getWidth());
		this.gs = ug.getGameState();
		border = ug.getWorldRenderer().getBorderRenderer().new Border(polys,HIGHLIGHT_COLOUR);
		ug.addEventHandler(new Handler());
		
		noHover();
	}
	
	private void noHover() {
		useLabelsUpTo(-1);
		//setLabel(0, "Hover over a region for information.");
		border.remove();
		//setMiddle(0,false);
	}
	
	public void setVisible(boolean b) { noHover(); visible = b; }

	@Override
	public Colour hovered(Region r, MouseEvent e) {
		hover = r;
		performUpdate();
		return null;
	}
	
	public void update(Region r) {
		if(r==null || r==hover)
			performUpdate();
	}
	
	private void performUpdate() {
		if(hover!=null && visible) {
			if( shift ) {
				showPlayerInfo();
				highlightPlayer();
			} else if( ctrl ) {
				showGroupInfo();
				highlightGroup();
				
			} else {
				showRegionInfo();
				border.remove();
			}
		} else
			noHover();
	}
	
	private void addSoldierItems(LinkedList<String> strs, int[] rtct, int[] rsct) {
		boolean show=false;
		for(RegionType rt : gs.getWorld().getRegionTypes())
			if( rt.hasCombo() )
				if( addItem(strs,rtct[rt.getId()],rt.getName(),rt.getSoldiersFor(rtct[rt.getId()])) )
					show = true;
		if( !show )
			strs.pollLast();
		
		show=false;
		strs.add("");
		for(ResourceType rsc : gs.getWorld().getResourceTypes())
			if( addItem(strs,rsct[rsc.getId()],rsc.getName(),rsc.getSoldiersFor(rsct[rsc.getId()])) )
				show = true;
		if( !show )
			strs.pollLast();
	}
	
	private void showPlayerInfo() {
		LinkedList<String> strs = new LinkedList<String>();
		if(!hover.isOwned())
			showRegionInfo();
		else {
			int[] rtct = new int[gs.getWorld().getRegionTypeCount()];
			int[] rsct = new int[gs.getWorld().getResourceTypeCount()];
			int sdPerTurn=0, sdTotal=0, sdLost=0, rgTotal=0, rgDiscon=0, rgCaps=0;
			for(int i=0; i<rtct.length; ++i) rtct[i] = 0;
			for(int i=0; i<rsct.length; ++i) rsct[i] = 0;
			for(GroupManager.Group g: gs.getGroupManager().getGroups(hover.getOwner())) {
				if( g.containsCapital() ) {
					g.addRegionTypeCounts(rtct);
					g.addResourceCounts(rsct);
					sdPerTurn += g.getSoldiersPerTurn();
					rgCaps += g.getCapitalCount();
				} else {
					sdLost += g.getSoldiersPerTurn();
					rgDiscon += g.getRegions().size();
				}
				rgTotal += g.getRegions().size();
				
				for(Region r:g.getRegions())
					sdTotal += r.getSoldiers();
			}
			
			strs.add(hover.getOwner().getName());
			strs.add("Owns " + rgTotal + " territories (" + rgCaps + " capitals, " + rgDiscon + " disconnected)" );
			strs.add("");
			strs.add("Territory info (excluding disconnected):");
			addSoldierItems(strs,rtct,rsct);
			strs.add("");
			strs.add("Produces " + GameGui.ntroop(sdPerTurn) + " per turn (" + sdLost + " lost, " + sdTotal + " owned)");
			showInfo(strs);
		}
	}
	
	private void showRegionInfo() {
		LinkedList<String> strs = new LinkedList<String>();
		strs.add(hover.getName() + " (" + hover.getType().getName() + ")");
		if( !hover.isOwned() )
			strs.add("Unowned");
		else {
			strs.add("Owned by " + hover.getOwner().getName() + " (" + GameGui.ntroop(hover.getSoldiers()) + ")");
			if(!gs.getGroupManager().getGroup(hover).containsCapital())
				strs.add("DISCONNECTED");
		}
		
		if(hover.getResources().length > 0) {
			String rscline = "Resources: " + (hover.getResources())[0].getName();
			
			for(int i=1; i<hover.getResources().length; ++i) {
				rscline += ", " + (hover.getResources())[i].getName();
			}
			
			strs.add(rscline);
		} else
			strs.add("Resources: None");
		/*
		if(hover.isOwned()) {
			strs.add("");
			strs.add("Hold <CTRL> for info about the group.");
			strs.add("Hold <SHIFT> for info about the player.");
		}*/
		showInfo(strs);
		
	}
	
	private boolean addItem(Collection<String> items, int count, String name, int value) {
		if(count==0) return false;
		if(value>0)
			items.add(count + " x " + name + " = +" + value);
		else
			items.add(count + " x " + name);
		return true;
	}
	
	private void showGroupInfo() {
		LinkedList<String> strs = new LinkedList<String>();
		
		GroupManager.Group g = gs.getGroupManager().getGroup(hover);
		
		if( g == null ) {
			showRegionInfo();
		} else {
			strs.add("Group owned by " + g.getOwner().getName());
			if(!g.containsCapital())
				strs.add("DISCONNECTED");
			strs.add("");
			strs.add("Territory info:");
			addSoldierItems(strs,g.getRegionTypesCounts(), g.getResourceCounts());
			strs.add("");
			String ntr = GameGui.ntroop(g.getSoldiersPerTurn());
			if( g.getSoldiersPerTurn()>0 ) {
				if(g.containsCapital()) {
					strs.add("In total the group produces " + ntr + " per turn.");
				} else
					strs.add("In total " + ntr + " are lost per turn.");
			} else
				strs.add("This group doesn't produce any troops.");
			showInfo(strs);
		}
	}
	
	private void showInfo( Collection<String> strs ) {
		int i = strs.size()-1;
		useLabelsUpTo(i);
		for(String st: strs)
			setLabel(i--,st);
	}
	
	private void highlightPlayer() {
		polys.clear();
		for(GroupManager.Group g:gs.getGroupManager().getGroups(hover.getOwner()))
			polys.addAll( g.getPolygons() );
		border.add();
	}
	
	private void highlightGroup() {
		
		polys.clear();
		GroupManager.Group g = gs.getGroupManager().getGroup(hover);
		if(g!=null) {
			polys.addAll( g.getPolygons() );
			border.add();
		}
	}

	@Override
	public void selected(Region r, MouseEvent e) {
		// do nothing
	}
	
}
